/*
 * adaboost_facedetect.cpp
 *
 *  Created on: 2016年3月13日
 *      Author: guyadong
 */
#include <iostream>
#include <cmath>
#include <stdexcept>
#include <sstream>
#include <vector>
#include "assert_macros.h"
#include "adaboost_facedetect_old.h"
#include "file_utilits.h"
#ifdef _MSC_VER
#pragma  warning( disable: 4244 )
#endif
namespace gdface{
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CAdaboostFaceDetect::CAdaboostFaceDetect(const std::string& file):CAdaboostFaceDetect(std::istringstream (gdface::load_string(file.data()))){
}
CAdaboostFaceDetect::CAdaboostFaceDetect(std::istream&& in) {
	try {
		hFeature = std::vector<FEATHER>(FEATHER_NUM);
	} catch (std::exception &e) {
		std::cerr << ERROR_STR(e.what()) << std::endl;
		exit(0);
	} catch (...) {
		std::cerr << ERROR_STR("unknow error") << std::endl;
		exit(0);
	}
	Cas.Feather = hFeature.data();
	in.read((char*) (&Cas.CasNum), sizeof(int));
	in.read((char*) (Cas.FeaNumPerLayer), 50 * sizeof(int));
	in.read((char*) (&Cas.FeatherNumPerCas), sizeof(int));
	in.read((char*) (Cas.LayerWeight), 50 * sizeof(double));
	in.read((char*) (Cas.Weight), 1600 * sizeof(double));
	in.read((char*) Cas.Feather, sizeof(FEATHER) * FEATHER_NUM);
	///////////////////////////added 2004/6/5
	FEATHER* f = Cas.Feather;
	for (int i = 0; i < FEATHER_NUM; i++) {
		if (f->RectangleNum == 3) {
			f->unitWidth = f->Width / 3;
			f->unitHeight = (f->Width / 3) * f->Height;
			f->CorrectNum = f->x + f->unitWidth;
			f->NonfaceCorrectNum = f->x + f->unitWidth * 2;
			f->Valve = f->x + f->Width;
		}
		if (f->RectangleNum == 2) {
			if (f->Up_Down) {
				f->unitHeight = f->Height / 2;
				f->CorrectNum = f->y + f->unitHeight;
				f->NonfaceCorrectNum = f->y + f->Height;
				f->Valve = f->x + f->Width;
			} else {
				f->unitWidth = f->Width / 2;
				f->CorrectNum = f->x + f->unitWidth;
				f->NonfaceCorrectNum = f->x + f->Width;
				f->Valve = f->y + f->Height;
			}
		}
		if (f->RectangleNum == 4) {
			f->unitHeight = f->Height / 2;
			f->unitWidth = f->Width / 2;
			f->CorrectNum = f->x + f->unitWidth;
			f->NonfaceCorrectNum = f->y + f->unitHeight;
		}

		f++;
	}
	/////////////////////add end
}



bool CAdaboostFaceDetect::RunFaceDetector(unsigned char * pImage, int Width, int Height, FACE_LOCATION * rface, int * FaceNumber)
{
	//////////////////////added 2004/6/5
	int ShiftPos = 0;
	int mm = 1;
	while(Width > mm)
	{
		mm = mm*2;
		ShiftPos += 1;
	}
	std::vector<uint8_t> hIma(mm*Height);
	uint8_t * pIma = NULL;
	pIma = hIma.data();

	for(int l1 = 0; l1 < Height; l1++)
	for(int l2 = 0; l2 < mm; l2++)
		pIma[l1*mm+l2] = 0;
	for(int l1 = 0; l1 < Height; l1++)
		memcpy(pIma + l1 * mm, pImage + l1 * Width, Width);

	unsigned char * pIm = pImage;
	pImage = pIma;
	int OrigWidth = Width;
	Width = mm;
	//////////////////////add end

    FACEINFO face[1000];
	int Win_Size = 24;

	std::vector<long> hInte (mm*Height);
	std::vector<uint32_t> hInteSqur (mm*Height);
	long * pInte = NULL;
	uint32_t * pInteSqur = NULL;
	pInte = hInte.data();
	pInteSqur = hInteSqur.data();

	IntegralE(pImage,&Width,&Height,pInte);
	IntegralSqurE(pImage,&Width,&Height,pInteSqur);

	//为积分图和平方积分图分配空间

	int j = 0;
	int PosX = 0,PosY = 0,Layer = 0,SF = 0,PFea = 0;
	float Difference = 0,Mean;
	double Variance = 0;
	FEATHER * tempf = Cas.Feather,* LayerBeginFeather = NULL;
	int NextFace = 0,Measure[ScaleSize];
	double Correct = 0;

	int k = 0;int SqurMeasure[ScaleSize];
	int FirstFaceNumber = 0;

	int l = 0;

	for(int i = 0; i < 2; i++)
		Face.DetectedFaceNum[i] = 0;

	for(int i = StartScaleSize; i < ScaleSize; i++)
	{
		Measure[i] = int( Win_Size * pow(SCALE,i) + 0.9);
		SqurMeasure[i] = Measure[i]*Measure[i];
	}

	float EnlargeRate = 1;
	int PACE = 1;

	//-------------Scale = StartScaleSize------------------
	/******************************** BEGIN: 方法*********************************/
	int t1 = 0,t2 = 0,t3 = 0,t4 = 0;
	double t5 = 0;
	int t8 = 0;
	int t9 = 0;
	int t10 = 0;
	int t11 = 0;
	int tt1 = 0, tt2 = 0, tt3 = 0, tt4 = 0;
	int tt5 = 0;
	int tt6 = 0, tt7 = 0, tt8 = 0, tt9 = 0;
	long x1=0,x2=0,x3=0,x4=0,x5=0,x6=0,x7=0,x8=0,x9=0;
	tempf = Cas.Feather;

	int TPace = 1;
	int WTPace = 1;

	for(l=StartScaleSize;l<ScaleSize;l++)
	{
		double MAXVar = MAXVAR;
		double MINVar = MINVAR;
		MAXVar = MAXVar*MAXVar;
		MINVar = MINVar*MINVar;

		if ((int( Win_Size * EnlargeRate ) > Width)||(int( Win_Size * EnlargeRate ) > Height))
			break;
		Face.DetectedFaceNum[0] = 0;

		t5 = double(SqurMeasure[l]);

		tempf = Cas.Feather + Cas.FeatherNumPerCas *l;
		double sss = tempf->DValve * tempf->DValve;
		PACE = int(EnlargeRate);
		TPace = (PACE<<1);
		//PACE = (PACE<<1);   //add  7.15
		//TPace = (PACE<<2);   //add 7.15
		WTPace = (PACE)*Width;
		for(PosY = 1, t1 = Measure[l] * Width, t3 = 0, tt1 = tempf->y * Width, tt2 = (tempf->y + (tempf->Height>>1)) * Width, tt3 = (tempf->y + tempf->Height) * Width; PosY < Height - Measure[l]; PosY = PosY + PACE, t1 = t1 + WTPace, t3 = t3 + WTPace, tt1 = tt1 + WTPace, tt2 = tt2 + WTPace, tt3 = tt3 + WTPace)
		{
			for(PosX = 1, t2 = Measure[l], t4 = 0, tt4 = tempf->x, tt5 = tempf->x + tempf->Width; PosX < OrigWidth - Measure[l]; PosX = PosX + (TPace), t2 += (TPace), t4 += (TPace), tt4 += (TPace), tt5 += (TPace))
			{
				/*********************************BEGIN: 计算方差**********************************/
				t8 = t1+t2; t9 = t1+t4; t10 = t3 + t2; t11 = t3+t4;
				Mean = ((*(pInte + t8)-*(pInte+t10)-*(pInte+t9)+*(pInte+t11)) / t5);
				Variance = (((*(pInteSqur+t8)-*(pInteSqur+t10)-*(pInteSqur+t9)+*(pInteSqur+t11)) / t5) - Mean * Mean);
				/*********************************END: 计算方差**********************************/
				//if(Variance >= 25)
				if((Variance > MINVar)
					&&(Variance < MAXVar))
				{
					Correct = 0;
					/****************************************** BEGIN: 优化计算特征值 *********************************/
					x1 = *(pInte + tt1 + tt4);
					x2 = *(pInte + tt1 + tt5);
					x3 = *(pInte + tt2 + tt4);
					x5 = *(pInte + tt3 + tt4);
					x4 = *(pInte + tt2 + tt5);
					x6 = *(pInte + tt3 + tt5);
					Difference = ((x6-x5+((x3 -x4) << 1))  -  (x1-x2));
					/****************************************** END: 优化计算特征值 *********************************/
					if ((Difference > 0)&&((Difference * Difference) > (sss * Variance) ))
					{
						Face.DetectedFace[0][Face.DetectedFaceNum[0]].UpX = PosX;
						Face.DetectedFace[0][Face.DetectedFaceNum[0]].UpY = PosY;
						Face.DetectedFace[0][Face.DetectedFaceNum[0]].Mean = Mean;
						Face.DetectedFace[0][Face.DetectedFaceNum[0]].Variance = Variance;

						Face.DetectedFaceNum[0] += 1;
					}
				}

			}
		}
		/******************************** END: 方法*********************************/
		tempf++;

		FirstFaceNumber = Face.DetectedFaceNum[0];
		PFea = 1;
		for(Layer=1; Layer < 19; Layer++)
		{
			LayerBeginFeather = tempf;
			int i = 0;
			while(i < FirstFaceNumber)
			{
				Correct = 0;
				tempf = LayerBeginFeather;
				PosX = Face.DetectedFace[0][i].UpX - 1;
				PosY = Face.DetectedFace[0][i].UpY - 1;
				for(SF = 0; SF < Cas.FeaNumPerLayer[Layer]; SF++)
				{
					/*************************************BEGIN: 特征值变化**********************************/
					if(tempf->RectangleNum == 2)
					{
						if(tempf->Up_Down)
						{
							tt1 = ((PosY + tempf->y)<<ShiftPos);
							tt2 = ((PosY + tempf->CorrectNum)<<ShiftPos);
							tt3 = ((PosY + tempf->NonfaceCorrectNum)<<ShiftPos);
							tt4 = (PosX + tempf->Valve);
							tt5 = (PosX + tempf->x);
							x1 = *(pInte + tt1 + tt5);
							x2 = *(pInte + tt1 + tt4);
							x3 = *(pInte + tt5 + tt2);
							x5 = *(pInte + tt5 + tt3);
							x4 = *(pInte + tt4 + tt2);
							x6 = *(pInte + tt4 + tt3);
							Difference = ((x6-x5+((x3-x4)<<1))  -  (x1-x2));
						}
						else
						{
							tt1 = ((PosY + tempf->y)<<ShiftPos);
							tt2 = ((PosY + tempf->Valve)<<ShiftPos);
							tt3 = (PosX + tempf->x);
							tt4 = (PosX + tempf->CorrectNum);
							tt5 = (PosX + tempf->NonfaceCorrectNum);
							x1 = *(pInte + tt1 + tt3);
							x2 = *(pInte + tt1 + tt4);
							x3 = *(pInte + tt1 + tt5);
							x4 = *(pInte + tt2 + tt3);
							x5 = *(pInte + tt2 + tt4);
							x6 = *(pInte + tt2 + tt5);
							Difference = ((x6-x3+((x2-x5)<<1))  -  (x1-x4));
						}
					}
					else if(tempf->RectangleNum == 3)
					{
						tt1 = ((PosY + tempf->y)<<ShiftPos);
						tt2 = ((PosY + tempf->y+tempf->Height)<<ShiftPos);
						tt3 = (PosX + tempf->x);
						tt4 = (PosX + tempf->CorrectNum);
						tt5 = (PosX + tempf->NonfaceCorrectNum);
						tt6 = (PosX + tempf->Valve);
						x1 = *(pInte+tt1+tt3);
						x2 = *(pInte+tt1+tt4);
						x3 = *(pInte+tt1+tt5);
						x4 = *(pInte+tt1+tt6);
						x5 = *(pInte+tt2+tt3);
						x6 = *(pInte+tt2+tt4);
						x7 = *(pInte+tt2+tt5);
						x8 = *(pInte+tt2+tt6);
						Difference =
							((((x6+x3)<<1)-((x2+x7)<<1)-x5+x1  +  x8-x4)
							-
							tempf->unitHeight * Face.DetectedFace[0][i].Mean);
					}
					else if(tempf->RectangleNum == 4)
					{
						tt1 = ((PosY + tempf->y)<<ShiftPos);
						tt2 = ((PosY + tempf->y+(tempf->unitHeight))<<ShiftPos);
						tt3 = ((PosY + tempf->y+tempf->Height)<<ShiftPos);
						tt4 = (PosX + tempf->x);
						tt5 = (PosX + tempf->x+(tempf->unitWidth));
						tt6 = (PosX + tempf->x+tempf->Width);
						x1 = *(pInte+tt1+tt4);
						x2 = *(pInte+tt1+tt5);
						x3 = *(pInte+tt1+tt6);
						x4 = *(pInte+tt2+tt4);
						x5 = *(pInte+tt2+tt5);
						x6 = *(pInte+tt2+tt6);
						x7 = *(pInte+tt3+tt4);
						x8 = *(pInte+tt3+tt5);
						x9 = *(pInte+tt3+tt6);
						Difference =
							(((((x5<<1)-x4-x8-x6-x2)<<1) + x1 + x9)
							+
							(x7 +x3));
					}
					else continue;
					/*************************************BEGIN: 特征值变化**********************************/
					if(tempf->Sign)
					{
						if (tempf->DValve > 0)
						{
							if(Difference > 0)
								if(tempf->DValve * tempf->DValve * Face.DetectedFace[0][i].Variance <
									Difference * Difference)
										Correct += Cas.Weight[SF+PFea];
						}
						else
						{
							if(Difference <= 0)
							{
								if(tempf->DValve * tempf->DValve * Face.DetectedFace[0][i].Variance >
									Difference * Difference)
										Correct += Cas.Weight[SF+PFea];
							}
							else
							{
								Correct += Cas.Weight[SF+PFea];
							}
						}
					}
					else
					{
						if (tempf->DValve > 0)
						{
							if(Difference > 0)
							{
								if(tempf->DValve * tempf->DValve * Face.DetectedFace[0][i].Variance >
									Difference * Difference)
										Correct += Cas.Weight[SF+PFea];
							}
							else
								Correct += Cas.Weight[SF+PFea];
						}
						else
						{
							if(Difference <= 0)
								if(tempf->DValve * tempf->DValve * Face.DetectedFace[0][i].Variance <
									Difference * Difference)
										Correct += Cas.Weight[SF+PFea];
						}
					}
					tempf++;
				}
				if(Cas.LayerWeight[Layer] > Correct)
				{
					Face.DetectedFaceNum[0]--;
					Face.DetectedFace[0][i].UpX = -1;
				}
				i++;
			}
			PFea += Cas.FeaNumPerLayer[Layer];

			Face.DetectedFaceNum[0] = 0;
			for(int loop = 0; loop < FirstFaceNumber; loop++)
			{
				if((Face.DetectedFace[0][loop].UpX!=-1))
				{
					Face.DetectedFace[0][Face.DetectedFaceNum[0]].UpX = Face.DetectedFace[0][loop].UpX;
					Face.DetectedFace[0][Face.DetectedFaceNum[0]].UpY = Face.DetectedFace[0][loop].UpY;
					Face.DetectedFace[0][Face.DetectedFaceNum[0]].Variance = Face.DetectedFace[0][loop].Variance;
					Face.DetectedFace[0][Face.DetectedFaceNum[0]].Mean = Face.DetectedFace[0][loop].Mean;
					Face.DetectedFaceNum[0]++;
				}
			}
			FirstFaceNumber = Face.DetectedFaceNum[0];
		}
		j = 0;
		for(int i = 0; i < FirstFaceNumber; i++)
		{
			Face.DetectedFace[1][Face.DetectedFaceNum[1]].UpX = Face.DetectedFace[0][i].UpX;
			Face.DetectedFace[1][Face.DetectedFaceNum[1]].UpY = Face.DetectedFace[0][i].UpY;
			Face.DetectedFace[1][Face.DetectedFaceNum[1]].DownX = Face.DetectedFace[0][i].UpX+ Measure[l];
			Face.DetectedFace[1][Face.DetectedFaceNum[1]].DownY = Face.DetectedFace[0][i].UpY+ Measure[l];
			Face.DetectedFaceNum[1]++;
		}
		//应该有一个处理，使得人脸检测过程中使用的占存人脸内存能够复用
		EnlargeRate *= (SCALE);
	}
	/**************去除重框*******************
	(Paul Viola's strategy to combine overlapping detections)*/


	Link  CurrHeadFace,* CurrTailFace = NULL,* CurrDispFace = NULL;
	int TotalFaceDispose = 0;

	*FaceNumber = 0;

	while (true)
	{
		//如果所有的脸都已被处理过了，退出
		if (TotalFaceDispose == Face.DetectedFaceNum[1])
			break;
		//如果所有的脸都已被处理过了，退出

		//预处理，以上挑出第一张脸作为初始准备整合
		for(j = 0; j < Face.DetectedFaceNum[1]; j++)
		{
			if (Face.DetectedFace[1][j].DownX != -1)
			{
				//将此脸移动到已处理过的链表里
				CurrHeadFace.face.DownX = Face.DetectedFace[1][j].DownX;
				CurrHeadFace.face.DownY = Face.DetectedFace[1][j].DownY;
				CurrHeadFace.face.UpX = Face.DetectedFace[1][j].UpX;
				CurrHeadFace.face.UpY = Face.DetectedFace[1][j].UpY;
				CurrTailFace = &CurrHeadFace;
				CurrHeadFace.next = NULL;
				//将此脸移动到已处理过的链表里

				//将此脸从待处理人脸数组中删除
				Face.DetectedFace[1][j].DownX = -1;
				Face.DetectedFace[1][j].DownY = -1;
				Face.DetectedFace[1][j].UpX = -1;
				Face.DetectedFace[1][j].UpY = -1;
				//将此脸从待处理人脸数组中删除
				TotalFaceDispose++;
				break;
			}
		}
		//预处理，以上挑出第一张脸作为初始准备整合
		CurrDispFace = &CurrHeadFace;
		CurrTailFace = &CurrHeadFace;
		//选出一个连通区域
		while (CurrDispFace != NULL)
		{
			for(j = 0; j < Face.DetectedFaceNum[1]; j++)
			{
				if (Face.DetectedFace[1][j].DownX != -1)
				{
					if  (
						((
						((Face.DetectedFace[1][j].UpX >= CurrDispFace->face.UpX)
						&&(Face.DetectedFace[1][j].UpX <= CurrDispFace->face.DownX))
						||
						((Face.DetectedFace[1][j].DownX >= CurrDispFace->face.UpX)
						&&(Face.DetectedFace[1][j].DownX <= CurrDispFace->face.DownX))
						)
						&&
						(
						((Face.DetectedFace[1][j].UpY >= CurrDispFace->face.UpY)
						&&(Face.DetectedFace[1][j].UpY <= CurrDispFace->face.DownY))
						||
						((Face.DetectedFace[1][j].DownY >= CurrDispFace->face.UpY)
						&&(Face.DetectedFace[1][j].DownY <= CurrDispFace->face.DownY))
						))
						||
						((
						((Face.DetectedFace[1][j].UpX <= CurrDispFace->face.UpX)
						&&(Face.DetectedFace[1][j].DownX >= CurrDispFace->face.UpX))
						||
						((Face.DetectedFace[1][j].UpX <= CurrDispFace->face.DownX)
						&&(Face.DetectedFace[1][j].DownX >= CurrDispFace->face.DownX))
						)
						&&
						(
						((Face.DetectedFace[1][j].UpY <= CurrDispFace->face.UpY)
						&&(Face.DetectedFace[1][j].DownY >= CurrDispFace->face.UpY))
						||
						((Face.DetectedFace[1][j].UpY <= CurrDispFace->face.DownY)
						&&(Face.DetectedFace[1][j].DownY >= CurrDispFace->face.DownY))
						))
						)//判断重框
					{
						//将检测到的重叠的结果加入到当前人脸链表中
						CurrTailFace->next = new Link;
						CurrTailFace->next->face.DownX = Face.DetectedFace[1][j].DownX;
						CurrTailFace->next->face.DownY = Face.DetectedFace[1][j].DownY;
						CurrTailFace->next->face.UpX = Face.DetectedFace[1][j].UpX;
						CurrTailFace->next->face.UpY = Face.DetectedFace[1][j].UpY;
						CurrTailFace->next->next = NULL;
						CurrTailFace = CurrTailFace->next;
						//将刚刚处理过的检测结果从分级检测结果数组里去除
						Face.DetectedFace[1][j].DownX = -1;
						Face.DetectedFace[1][j].DownY = -1;
						Face.DetectedFace[1][j].UpX = -1;
						Face.DetectedFace[1][j].UpY = -1;
						TotalFaceDispose++;
					}//if
				}//if
			}//for
			CurrDispFace = CurrDispFace->next;
		}
		//选出一个连通区域
		//////添加本次选出连通区域
		(*FaceNumber) = (*FaceNumber) + 1;

		face[*FaceNumber-1].DownX = CurrHeadFace.face.DownX;
		face[*FaceNumber-1].DownY = CurrHeadFace.face.DownY;
		face[*FaceNumber-1].UpX = CurrHeadFace.face.UpX;
		face[*FaceNumber-1].UpY = CurrHeadFace.face.UpY;
		CurrDispFace = CurrHeadFace.next;
		CurrHeadFace.next = NULL;
		int TempTotalOverLapFace = 1;
		while (CurrDispFace != NULL)
		{
			face[*FaceNumber-1].DownX += CurrDispFace->face.DownX;
			face[*FaceNumber-1].DownY += CurrDispFace->face.DownY;
			face[*FaceNumber-1].UpX += CurrDispFace->face.UpX;
			face[*FaceNumber-1].UpY += CurrDispFace->face.UpY;
			TempTotalOverLapFace++;
			CurrTailFace = CurrDispFace;
			CurrDispFace = CurrDispFace->next;
			delete CurrTailFace;
			CurrTailFace = NULL;
		}
		face[*FaceNumber-1].DownX = face[*FaceNumber-1].DownX /TempTotalOverLapFace;
		face[*FaceNumber-1].DownY = face[*FaceNumber-1].DownY /TempTotalOverLapFace;
		face[*FaceNumber-1].UpX = face[*FaceNumber-1].UpX /TempTotalOverLapFace;
		face[*FaceNumber-1].UpY = face[*FaceNumber-1].UpY /TempTotalOverLapFace;
		//添加本次选出连通区域
	}
//	DeNONFaceDected (pImage,Width,Height,face,FaceNumber);
	/**************去除重框*********************/


	for(int i = 0; i < *FaceNumber; i++)
	{
		rface[i].upx = face[i].UpX;
		rface[i].upy = face[i].UpY;
		rface[i].width = face[i].DownX - face[i].UpX;
		rface[i].height = face[i].DownY - face[i].UpY;

		//wang 2004.1.9 add for organ location information
		rface[i].leftEyeArea.lui = face[i].UpX + 2*((float)rface[i].width/24);
		rface[i].leftEyeArea.luj = face[i].UpY + 2*((float)rface[i].height/24);   // 04.1.9
		rface[i].leftEyeArea.h = 8*((float)rface[i].height/24);     // 04.1.9
        rface[i].leftEyeArea.w = 8*((float)rface[i].width/24);

		rface[i].rightEyeArea.lui = face[i].UpX + 14*((float)rface[i].width/24);
		rface[i].rightEyeArea.luj = face[i].UpY + 2*((float)rface[i].height/24);  // 04.1.9
		rface[i].rightEyeArea.h = 8*((float)rface[i].height/24);      // 04.1.9
        rface[i].rightEyeArea.w = 8*((float)rface[i].width/24);

		rface[i].noseArea.lui = face[i].UpX + 9*((float)rface[i].width/24);
        rface[i].noseArea.luj = face[i].UpY + 13*((float)rface[i].height/24);
        rface[i].noseArea.h = 3*((float)rface[i].height/24);
        rface[i].noseArea.w = 6*((float)rface[i].width/24);

		rface[i].mouthArea.lui = face[i].UpX + 8*((float)rface[i].width/24);
        rface[i].mouthArea.luj = face[i].UpY + 20*((float)rface[i].height/24);
        rface[i].mouthArea.h = 3*((float)rface[i].height/24);
        rface[i].mouthArea.w = 8*((float)rface[i].width/24);
        ////////////////////////////////////////////////////

		//wanggt add 12.25
		//显示检测结果
/*		int n, m;
	    for(n=0;n<rface[i].height;n++)
	        {
	           for(m=0;m<=rface[i].width;m++)
		       {
			     *(pIm+(rface[i].upy +n)*OrigWidth+rface[i].upx)=255;
			     *(pIm+(rface[i].upy +rface[i].height)*OrigWidth+(rface[i].upx+m))=255;
			     *(pIm+(rface[i].upy +n)*OrigWidth+(rface[i].upx+rface[i].width))=255;
			     *(pIm+rface[i].upy *OrigWidth+(rface[i].upx+m))=255;
		       }
	       }
*/		  //////////////////////////
	}

	pImage = pIm;

	return true;
}
void CAdaboostFaceDetect::IntegralE(unsigned char *Image, int *width, int *height, long *IntegralImage)
{
	int i=0,j=0;
	long s=0;
	unsigned char * CurrPixel = Image;
	long * CurrSqurPixel = IntegralImage;
	long * PrevSqurPixel = IntegralImage;
	*CurrSqurPixel = *CurrPixel;
	CurrSqurPixel++;
	CurrPixel++;

	for(i = 1;i<*width;i++)
	{
		*CurrSqurPixel += *PrevSqurPixel+*CurrPixel;
		CurrSqurPixel++;
		CurrPixel++;
		PrevSqurPixel++;
	}
	PrevSqurPixel = IntegralImage;
	for(i=1;i<*height;i++)
	{
		s=0;
		for(j=0;j<*width;j++)
		{
			s = s + *CurrPixel;
			*CurrSqurPixel = *PrevSqurPixel + s;
			CurrPixel++;
			CurrSqurPixel++;
			PrevSqurPixel++;
		}
	}
}
void CAdaboostFaceDetect::IntegralSqurE(unsigned char *Image, int *width, int *height, uint32_t *IntegralImage)
{
	int i=0,j=0;
	long s=0;
	unsigned char * CurrPixel = Image;
	uint32_t * CurrSqurPixel = IntegralImage;
	uint32_t * PrevSqurPixel = IntegralImage;
	*CurrSqurPixel = (*CurrPixel)*(*CurrPixel);
	CurrSqurPixel++;
	CurrPixel++;

	for(i = 1;i<*width;i++)
	{
		*CurrSqurPixel += *PrevSqurPixel+(*CurrPixel)*(*CurrPixel);
		CurrSqurPixel++;
		CurrPixel++;
		PrevSqurPixel++;
	}
	PrevSqurPixel = IntegralImage;
	for(i=1;i<*height;i++)
	{
		s=0;
		for(j=0;j<*width;j++)
		{
			s = s + (*CurrPixel)*(*CurrPixel);
			*CurrSqurPixel = *PrevSqurPixel + s;
			CurrPixel++;
			CurrSqurPixel++;
			PrevSqurPixel++;
		}
	}
}
void CAdaboostFaceDetect::MagnifyFeather()
{
	int j = 0;
	for(int i = 0; i < 13; i++)
	{
		for(j = 0; j < Cas.FeatherNumPerCas; j++)
		{
			((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->x = (int)((((FEATHER *)(Cas.Feather)+j)->x)*pow(SCALE,i)+0.5);
			((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->y = int((((FEATHER *)(Cas.Feather)+j)->y)*pow(SCALE,i)+0.5);
			if(((FEATHER *)(Cas.Feather)+j)->RectangleNum==2)
			{
				if(!((FEATHER *)(Cas.Feather)+j)->Up_Down)
				{
					((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->Width = int((((FEATHER *)(Cas.Feather)+j)->Width)*pow(SCALE,i)+0.5)/2*2;
					((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->Height = (int((((FEATHER *)(Cas.Feather)+j)->Height)*pow(SCALE,i)+0.5));
				}
				else
				{
					((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->Width = int((((FEATHER *)(Cas.Feather)+j)->Width)*pow(SCALE,i)+0.5);
					((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->Height = (int((((FEATHER *)(Cas.Feather)+j)->Height)*pow(SCALE,i)+0.5))/2*2;
				}
			}
			if(Cas.Feather[j].RectangleNum==3)
			{
				((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->Width = int((((FEATHER *)(Cas.Feather)+j)->Width)*pow(SCALE,i)+0.5)/3*3;
				((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->Height = (int((((FEATHER *)(Cas.Feather)+j)->Height)*pow(SCALE,i)+0.5));
			}
			if(Cas.Feather[j].RectangleNum==4)
			{
				((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->Width = int((((FEATHER *)(Cas.Feather)+j)->Width)*pow(SCALE,i)+0.5)/2*2;
				((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->Height = (int((((FEATHER *)(Cas.Feather)+j)->Height)*pow(SCALE,i)+0.5))/2*2;
			}
			((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->Up_Down = ((FEATHER *)(Cas.Feather)+j)->Up_Down;
			((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->Sign = ((FEATHER *)(Cas.Feather)+j)->Sign;
			(((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->Valve) = (((FEATHER *)(Cas.Feather)+j)->Valve);
			(((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->DValve) =
				double((((FEATHER *)(Cas.Feather)+j)->DValve)*(double
				(((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->Width*((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->Height)
				/double(((FEATHER *)(Cas.Feather)+j)->Width*((FEATHER *)(Cas.Feather)+j)->Height)));
			((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->RectangleNum = ((FEATHER *)(Cas.Feather)+j)->RectangleNum;
			((FEATHER *)(Cas.Feather)+j+Cas.FeatherNumPerCas*i)->CorrectNum = ((FEATHER *)(Cas.Feather)+j)->CorrectNum;
		}
	}
}
DETECTFACEINFO::DETECTFACEINFO()
{
	hFaceInfo = std::vector<FACEINFO>(FACEINFO_SIZE*2);

	pFaceInfo = (uint8_t *)(hFaceInfo.data());
	DetectedFace[0]=&hFaceInfo[0];
	DetectedFace[1]=&hFaceInfo[FACEINFO_SIZE];


}

DETECTFACEINFO::~DETECTFACEINFO()
{
}

#define M_PI 3.14159265359



}/* namespace gdface */


